#include <arrow/api.h>
#include <arrow/result.h>

#include <cstdint>
#include <iomanip>
#include <iostream>
#include <vector>

#include <arrow/api.h>
#include <arrow/compute/cast.h>
#include <arrow/compute/exec/expression.h>
#include <arrow/dataset/dataset.h>
#include <arrow/dataset/discovery.h>
#include <arrow/dataset/file_base.h>
#include <arrow/dataset/file_ipc.h>
#include <arrow/dataset/file_parquet.h>
#include <arrow/dataset/scanner.h>
#include <arrow/filesystem/filesystem.h>
#include <arrow/ipc/writer.h>
#include <arrow/util/iterator.h>
#include <parquet/arrow/writer.h>
#include <arrow/compute/api_aggregate.h>
#include <arrow/compute/api_scalar.h> 

using arrow::DoubleBuilder;
using arrow::Int64Builder;
using arrow::ListBuilder;
namespace fs = arrow::fs; 

#define ABORT_ON_FAILURE(expr)                     \
  do {                                             \
    arrow::Status status_ = (expr);                \
    if (!status_.ok()) {                           \
      std::cerr << status_.message() << std::endl; \
      abort();                                     \
    }                                              \
  } while (0);

//构建表数据
/*表结构
  a | b
  0 | 9
  1 | 8
  2 | 7
  3 | 6
  4 | 5
*/
std::shared_ptr<arrow::Table> CreateTable1() {
    auto schema =
            arrow::schema({arrow::field("a", arrow::int64()),arrow::field("b", arrow::int64())});
    std::shared_ptr<arrow::Array> array_a;
    std::shared_ptr<arrow::Array> array_b;

    arrow::NumericBuilder<arrow::Int64Type> builder;
    ABORT_ON_FAILURE(builder.AppendValues({0, 1, 2, 3, 4}));
    ABORT_ON_FAILURE(builder.Finish(&array_a));
    builder.Reset();
    ABORT_ON_FAILURE(builder.AppendValues({9, 8, 7, 6, 5}));
    ABORT_ON_FAILURE(builder.Finish(&array_b));
    
    builder.Reset();
    return arrow::Table::Make(schema, {array_a, array_b});
}


//表数据写入文件
std::string CreateExampleFeatherDataset(const std::shared_ptr<fs::FileSystem>& filesystem,
                                        const std::string& root_path) {
    auto base_path = root_path + "/feather_dataset";//文件夹路径
    ABORT_ON_FAILURE(filesystem->CreateDir(base_path));
    // Create an Arrow Table
    auto table = CreateTable1();
    // Write it into two Feather files
    auto output = filesystem->OpenOutputStream(base_path + "/data1.feather").ValueOrDie();  //写入的文件路径
    auto writer = arrow::ipc::MakeFileWriter(output.get(), table->schema()).ValueOrDie();//从stream sink and schema创建一个新的IPC文件写入器
    ABORT_ON_FAILURE(writer->WriteTable(*table));//通过创建 record batches序列来写可能是分块的表
    ABORT_ON_FAILURE(writer->Close());//写完关闭文件
    return base_path;
}